﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Xml;
using Headsight.BPMN2WF.BPMN.Model;

namespace Headsight.BPMN2WF.Transformation.BPMN2TransformerMappings.Config
{
    public class BPMN2WFTransformationConfigMap
    {
        public IBPMN2WFTransformation DestinationObject { get; private set; }
        public IList<BPMN2WFTransformationConfigMapCondition> Conditions { get; set; }

        public BPMN2WFTransformationConfigMap(IBPMN2WFTransformation destinationObject)
        {
            DestinationObject = destinationObject;
            Conditions = new List<BPMN2WFTransformationConfigMapCondition>();
        }

        public bool Matches(BPMNFlowNode node, Type typeOfFlowElement)
        {
            var matches = true;
            foreach (var condition in Conditions)
                matches = matches && condition.Matches(node, typeOfFlowElement);

            return matches;
        }

        public static BPMN2WFTransformationConfigMap FromXmlMappingNode(XmlNode mappingNode)
        {
            var assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.FullName == mappingNode.Attributes["assembly"].Value);
            if (assembly == null)
            {
                var assemblyName = new AssemblyName(mappingNode.Attributes["assembly"].Value);
                assembly = Assembly.Load(assemblyName);
                if (assembly == null)
                    throw new Exception(string.Format("The given Assembly [{0}] was not found. Please check if you added the assembly to the gac.", mappingNode.Attributes["assembly"].Value));
            }

            var type = assembly.GetType(mappingNode.Attributes["type"].Value);
            if (type == null)
                throw new Exception(string.Format("The given Type [{0}] was not found in Assembly [{1}].", mappingNode.Attributes["type"].Value, mappingNode.Attributes["assembly"].Value));

            var instance = Activator.CreateInstance(type) as IBPMN2WFTransformation;
            if (instance == null) return null;
            var map = new BPMN2WFTransformationConfigMap(instance);
            foreach (XmlNode conditionNode in mappingNode.SelectSingleNode("conditions").ChildNodes)
                map.Conditions.Add(BPMN2WFTransformationConfigMapCondition.FromXmlConditionNode(conditionNode));

            return map;
        }
    }
}
